package com.service.Impl;

import com.dto.CouponDto;
import com.dto.UserCouponDto;
import com.entity.Coupon;
import com.entity.User;
import com.entity.UserCoupon;
import com.exception.AddException;
import com.exception.DateNotFoundException;
import com.github.pagehelper.PageHelper;
import com.mapper.CouponMapper;
import com.mapper.UserCouponMapper;
import com.mapper.UserMapper;
import com.service.UserCouponService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName UserCouponServiceImpl
 * @Description 用户优惠券业务层实现类
 * @Author Kx
 * @Date 2025/5/29 11:03
 * @Version 1.0
 */
@Service("userCouponService")
public class UserCouponServiceImpl implements UserCouponService {
    private static final Log log = LogFactory.getLog(UserCouponServiceImpl.class);
    private final UserCouponMapper userCouponMapper;
    private final CouponMapper couponMapper;
    private final UserMapper userMapper;

    public UserCouponServiceImpl(UserCouponMapper userCouponMapper, CouponMapper couponMapper, UserMapper userMapper) {
        this.userCouponMapper = userCouponMapper;
        this.couponMapper = couponMapper;
        this.userMapper = userMapper;
    }

    /**
     * @param userCoupon : 用户优惠券信息
     * @author: kx
     * @date: 2025/5/29 11:05
     * @description: 添加用户优惠券信息
     */
    @Transactional
    @Override
    public void addUserCoupon(UserCoupon userCoupon) {
        try {
            // 获取优惠券信息
            Coupon coupon = couponMapper.findById(userCoupon.getCouponId());
            // 获取优惠券有效天数
            Integer validDays = coupon.getValidDays();
            // 获取当前时间
            LocalDateTime now = LocalDateTime.now();
            // 结束时间
            LocalDateTime endTime = now.plusDays(validDays);
            // 设置有效期开始时间为当前领取时间
            userCoupon.setStartTime(now);
            // 设置领取时间
            userCoupon.setCreateTime(now);
            // 添加结束时间
            userCoupon.setEndTime(endTime);
            // 添加用户优惠券信息
            userCouponMapper.addUserCoupon(userCoupon);
            // 减去优惠券数量
            couponMapper.updateCoupon(coupon);
        } catch (Exception e) {
            throw new AddException(1002, "添加用户优惠券失败");
        }
    }

    /**
     * @param userId : 用户id
     * @return com.dto.UserCouponDto
     * @author: kx
     * @date: 2025/5/29 11:48
     * @description: 根据用户id查询用户所有优惠券信息
     */
    @Override
    public UserCouponDto findByUserIdAndCouponId(Integer userId) {
        // 查询用户信息，若用户不存在则抛出异常
        User user = userMapper.selectUserInfoByAccountId(userId);
        if (user == null) {
            throw new DateNotFoundException(1001, "用户不存在");
        }

        // 查询用户的优惠券列表，若为空则抛出异常
        List<UserCoupon> userCouponList = userCouponMapper.findByUserId(userId);
        if (userCouponList == null || userCouponList.isEmpty()) {
            throw new DateNotFoundException(1001, "用户优惠券为空");
        }

        // 组装返回数据
        UserCouponDto userCouponDto = new UserCouponDto();
        userCouponDto.setUser(user);

        List<CouponDto> couponDtoList = new ArrayList<>();
        for (UserCoupon userCoupon : userCouponList) {
            // 查询优惠券模板信息
            Coupon coupon = couponMapper.findById(userCoupon.getCouponId());
            if (coupon == null) {
                // 记录警告日志（理论上不会出现，除非数据异常）
                log.warn("优惠券不存在，优惠券ID: " + userCoupon.getCouponId());
                continue; // 跳过无效优惠券
            }

            // 组装优惠券详情
            CouponDto couponDto = new CouponDto();
            couponDto.setUserCoupon(userCoupon);
            couponDto.setCoupon(coupon);
            couponDtoList.add(couponDto);
        }

        // 若所有优惠券均无效，抛出异常
        if (couponDtoList.isEmpty()) {
            throw new DateNotFoundException(1001, "用户优惠券无效");
        }

        userCouponDto.setCoupons(couponDtoList);
        return userCouponDto;
    }

    /**
     * @author: kx
     * @date: 2025/5/29 20:16
     * @description: 实时监听过期优惠券,并修改过期优惠券状态
    */
    @Scheduled(cron = "0 0/30 * * * ?") // 每30分钟执行一次
    @Transactional
    @Override
    public void checkAndUpdateExpiredCoupons() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        int pageNum = 1; // 当前页码
        int pageSize = 1000; // 每次查询1000条数据

        while (true) {
            // 使用分页插件
            PageHelper.startPage(pageNum, pageSize);
            // 获取过期优惠券ID
            List<Long> longs = userCouponMapper.selectExpiredCouponIds(now);
            // 判断是否有过期优惠券
            if (longs.isEmpty()) {
                break;
            }
            // 批量修改优惠券状态
            userCouponMapper.batchUpdateStatus(longs, null);
            // 下一页
            pageNum++;

            if (longs.size() < pageSize) {
                break;
            }
        }
    }
}
